package de.java.shortys.myhome.keymanager.controller;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;

import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

import de.java.shortys.utils.file.FileUtils;

public class KeyManager {

	private static final String[] CAHRACTERS = new String[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
			"L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
	private static final String[] NUMBERS = new String[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" };
	private static final int LENGTH = 12;
	private static final String FOLDER = "keymanager";
	private static final String FILE_ENDING = ".xml";
	private static Map<String, KeyManager> keymanagers;

	static {
		init();
	}

	public static KeyManager getManager(String key) {
		KeyManager keyManager = keymanagers.get(key);
		if (keyManager == null) {
			// FIXME Exception
			try {
				keyManager = new KeyManager(key);
			} catch (JDOMException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			keymanagers.put(key, keyManager);
		}

		return keyManager;
	}

	private static void init() {
		keymanagers = new TreeMap<String, KeyManager>();
		final File keymanagerfolder = FileUtils.getFolderFromClassPath(KeyManager.class.getClassLoader(), FOLDER, true);
		for (File keymanagerFile : keymanagerfolder.listFiles()) {
			final String name = keymanagerFile.getName().replaceAll(FILE_ENDING, "");
			// FIXME Exception?
			try {
				keymanagers.put(name, new KeyManager(name));
			} catch (JDOMException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private String name;

	private Document document;

	private List<String> keys;

	private File file;

	{
		keys = new ArrayList<String>();
	}

	public KeyManager(String name) throws JDOMException, IOException {
		this.name = name;
		initialize();
	}

	public void addKey(String key) {
		keys.add(key);
		Element newChild = new Element("key");
		newChild.setAttribute("value", key);
		document.getRootElement().addContent(newChild);
		writeDocument();
	}

	public void removeKey(String key) {
		keys.remove(key);
		removeContent(key);
		writeDocument();
	}

	@SuppressWarnings("unchecked")
	private void removeContent(String key) {
		Element root = document.getRootElement();
		for (Element child : (List<Element>) root.getChildren()) {
			String keyvalue = child.getAttributeValue("value");
			if (keyvalue.equals(key)) {
				root.removeContent(child);
				break;
			}
		}
		writeDocument();
	}

	public boolean exists(String key) {
		return keys.contains(key);
	}

	public String generateKey() {
		String key = null;
		do {
			key = getRandomKey();
		} while (keys.contains(key));
		addKey(key);
		return key;
	}

	public File getFile() {
		return file;
	}

	public String getName() {
		return name;
	}

	private String getRandomKey() {
		final Random rnd = new Random();
		final StringBuffer key = new StringBuffer();
		for (int i = 0; i < LENGTH; i++) {
			String[] box = getBox();
			key.append(box[rnd.nextInt(box.length)]);
		}

		return key.toString();
	}

	private String[] getBox() {
		Random rnd = new Random();
		int nextInt = rnd.nextInt(50);
		if (nextInt > 20) {
			return CAHRACTERS;
		}
		return NUMBERS;
	}

	@SuppressWarnings("unchecked")
	private void initialize() throws JDOMException, IOException {
		final File keymanagerfolder = FileUtils.getFolderFromClassPath(KeyManager.class.getClassLoader(), FOLDER, true);
		file = new File(keymanagerfolder.getAbsolutePath() + "/" + name + FILE_ENDING);
		SAXBuilder builder = new SAXBuilder();
		if (!file.exists()) {
			file.createNewFile();
			FileWriter fw = new FileWriter(file);
			fw.write("<keys>\n");
			fw.write("</keys>");
			fw.flush();
			fw.close();
		}
		document = builder.build(file);
		Element root = document.getRootElement();
		for (Element child : (List<Element>) root.getChildren()) {
			String keyvalue = child.getAttributeValue("value");
			keys.add(keyvalue);
		}
	}

	private void writeDocument() {
		XMLOutputter outputter = new XMLOutputter();
		// FIXME Exception?
		try {
			FileOutputStream output;
			output = new FileOutputStream(file);
			outputter.setFormat(Format.getPrettyFormat());
			outputter.output(document, output);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
